Set Data
What does it do?
Creates or updates (upserts) a JSON document in the customer-scoped data store under collection + key, with a required TTL. Optionally attaches tags for later filtering via list.
If a row with the same collection + key already exists and hasn't expired, it is updated (data, tags, and expiry all replaced). Otherwise a new row is created.
1. Syntax
<node_name>:
type: func
func_type: dataStorage
func_id: set
params:
collection: "<collection_name>"
key: "<record_key>"
data:
<arbitrary_json>
expiresIn: <positive_number>
expiresInUnit: "minutes" | "hours" | "days"
tags:
- "<tag>"
on_complete: <next_node>
required params
typetype of the nodefunc_typehere it will bedataStoragefunc_idwhat function are we calling (set)params.collectioncollection name. Must match^[a-zA-Z0-9_-]+$(letters, digits,_,-), max 100 charsparams.keyrecord key within the collection (non-empty, max 200 chars)params.dataJSON object to store (any serializable fields you need)params.expiresInpositive number, paired withexpiresInUnit. Max combined TTL is 7 days.params.expiresInUnitone of"minutes","hours","days"on_completenext node after the write succeeds
optional params
params.tagsarray of strings — used for tagged queries withlist. Max 50 tags per item, each up to 100 charson_failurefallback nodedepartmentassigns the chat to a departmentagentassigns the chat to a specific agent (email address or CRM ID as defined in the Texter agents manager)
Use snake_case for collection names — e.g. new_leads, sla_chats, campaign_events.
Use stable keys like %chat:channelInfo.id% (one row per phone number) so future bot sessions can find the same record.
2. Output
The upserted item DTO is stored at %state:node.<node_name>% — same shape as get returns. Useful for chaining (e.g. reading back the expiresAt or _id).
3. Examples
SLA timestamp row (24h TTL)
Tracks when the customer's chat went into an SLA state. Keyed by phone number so any later session finds the same record.
write_sla_row:
type: func
func_type: dataStorage
func_id: set
params:
collection: "sla_chats"
key: "%chat:channelInfo.id%"
data:
timestamp: "%time:now(\"x\")%"
chatId: "%chat:_id%"
expiresIn: 24
expiresInUnit: "hours"
on_complete: next_node
Tag a customer as a campaign participant
Tags make this row queryable later via list (e.g. "all customers who joined the icq campaign in the last 7 days").
save_campaign_participant:
type: func
func_type: dataStorage
func_id: set
params:
collection: "campaign_events"
key: "%chat:channelInfo.id%"
data:
source: "icq_campaign"
customerName: "%state:node.ask_name.text%"
tags:
- "icq_campaign"
- "%state:node.ask_interest.text%"
expiresIn: 7
expiresInUnit: "days"
on_complete: next_node
Cache an API lookup for an hour
Store an expensive lookup result so repeat conversations don't refetch.
cache_customer_lookup:
type: func
func_type: dataStorage
func_id: set
params:
collection: "customer_cache"
key: "%chat:channelInfo.id%"
data:
accountId: "%state:node.lookup.response.accountId%"
tier: "%state:node.lookup.response.tier%"
expiresIn: 60
expiresInUnit: "minutes"
on_complete: continue_flow
Calling set on an existing key replaces data, tags, and the expiry. There is no partial update — pass the full object you want stored.
Max TTL is 7 days. expiresIn: 8, expiresInUnit: "days" will fail validation.